對於app的許多動作,都需要瞭解lifecycle
本篇為google的教學文章,利用logging來觀察android lifecycles
activity每一個當下都有lifecycle的狀態,有以下幾種 (圖1)
onCreate()是每個activity必須首先執行的function
因為layout是透過onCreate()去inflate
當activity一初始化後,就會呼叫onCreate(),也只有在初始化後呼叫這一次,之後就會進入其它生命週期
接著須立刻呼叫super.onCreate()
這裡是呼叫父類別Activity下的onCreate()以確保父類別所做的初始化都有做到
在super.onCreate()
後加上
Log.i("MainActivity", "onCreate Called")
Log的用法.i表示information,第一個參數是tag,方便在logcat查詢時過濾訊息,通常會使用此class的name
第二個參數就是我們想要看到的訊息
在android studio執行run之後,到下方的Logcat console
在搜尋欄打我們要看的tag,此處為I/MainActivity
(分大小寫)
I
表示來自Log.i()
MainActivity
表示我們自訂的Log.i("MainActivity", "onCreate Called")
第一個參數這樣就表示要顯示符合我們條件的訊息(Log.i()的第二個參數 "onCreate Called")
當看到符合的訊息出現時,就表示這行Log所在位置的程式已被執行
這裡也就是說onCreate()已執行
緊接在onCreate()後的是onStart()
要onStart()執行之後,activity才會顯示在螢幕上
與onStart()相應的是onStop(),當app被滑掉不顯示在當前螢幕(按home鍵)時,activity會依照圖1的lifecycle箭頭方向,由onStart()走到onStop
等待將app叫回當前螢幕後,如logcat顯示不會回到onCreate(),是再次onStart(),並且是顯示回到activity被滑掉時最後狀態(這裡不知道是否因為onCreate()的savedInstanceState參數保存關係?)
若是用back返回鍵退出app,即使用最近程式(方塊鍵)叫回app,就會重新再進onCreate()
Timber是一個logging library,它會自動將其所在class的name當做tag
要使用Timber需要到dependencies implementation它
首先去 Timber project on GitHub,找目前的版本號並複製整行文字,例如implementation 'com.jakewharton.timber:timber:4.7.1'
回到專案,開啟build.gradle(Module:app),貼在dependencies區塊中
dependencies {
...
implementation 'com.jakewharton.timber:timber:4.7.1'
}
再來建立一個Application class
這是一個基礎class,也是一個主要物件被android用來與app之間互動,即使我們不去指定(通常也無需指定),android也會為app建立一個Application物件
在整個app的activity被初始化前,Application class就會先創建
因為Timber是整個app都會用到的logging library,需要在其它設定之前先初始化,因此要在Application class中先執行
建立自訂的Application class並繼承Application(),例如class ClickerApplication : Application() {..}
override其中的onCreate(),加入Timber並初始化,,全部像這樣
class ClickerApplication : Application() {
override fun onCreate(){
super.onCreate()
Timber.plant(Timber.DebugTree())
}
}
不是用default Application的話,我們就要到AndroidManifest.xml指明我們要改用的Application叫啥,不然app還是會用default Application,也就沒有Timber
<application
android:name=".ClickerApplication"
準備完成後,就可以將Log.i()改成Timber,不用再給tagTimber.i("onCreate called")
接著override其它的lifecycles來做觀察
override fun onResume() {
super.onResume()
Timber.i("onResume Called")
}
override fun onPause(){
super.onPause()
Timber.i("onPause")
}
override fun onStop(){
super.onStop()
Timber.i("onStop Called")
}
override fun onDestroy(){
super.onDestroy()
Timber.i("onDestroy Called")
}
override fun onRestart(){
super.onRestart()
Timber.i("onRestart Called")
}
上圖可以看到一執行app,就會有三個週期接續執行
由onCreate() -> onStart() -> onResume()
分別代表
再來用back鍵來完全關閉activity,可以看到llifecycle走到onDestroy()
當onDestroy()執行時,表示activity已完全結束,可以被Garbage collection
OS知道可以將這個物件從記憶體中清除掉,讓資源釋放出來
codelab這裡寫到
Your activity may also be completely shut down if your code manually calls the activity's finish() method, or if the user force-quits the app. (For example, the user can force-quit the app in the recents screen by clicking the X in the corner of the window.) The Android system may also shut down your activity on its own if your app has not been on-screen for a long time.
finish():Call this when your activity is done and should be closed.
請教EnPing有關finish()與onDestroy()的差別後,有稍微了解一些:
原來所有onXXXX()的方法,都不應該由我們呼叫,應該說lifecycle是由系統依照app被使用的情況而去呼叫
那finish()是我們可以另外告訴系統要把activity給結束掉的方法
當系統收到我們的程式碼呼叫finish()時,就會把activity註記為不要的物件,然後準備onPause(),onStop(),onDestory(),但呼叫這些lifecycle的時間依然是由系統控制,依情況可能快可能慢
這裡有一個重點是:
onCreate()和onDestroy()這二個頭尾,只會在那個activity物件的生命週期各被呼叫一次